# -*- coding:utf8 -*-
"""
采用文本的方式处理字典数据
其实应该采用ｊｓｏｎ保存是最稳妥的，但是对于unicode来说其可读性太差
"""
from __future__ import print_function
import codecs

from logger_utility.loggconfig import getLogger

logger = getLogger("TextDictProcess")


class TextDictBase(object):
    """
    基础的配置，配置字典之间的分割和字典内部key之间的分割
    """

    def __init__(self,
                 sn_pre='==========-----',
                 sn_post='-----==========',
                 key_pre='=====-----',
                 key_post='-----====='):
        self.sn_pre = sn_pre
        self.sn_post = sn_post
        self.key_pre = key_pre
        self.key_post = key_post


class TextDictReader(TextDictBase):
    """
    读取文件
    """

    def _section_begin(self, line):
        """
        一个段的开头
        :param line:
        :return:
        """
        if not (line.startswith(self.sn_pre) and line.endswith(self.sn_post)):
            return False

        line = line.replace(self.sn_pre, '').replace(self.sn_post, '')
        if line:
            try:
                id_ = int(line)
                return id_
            except BaseException:
                return False
        else:
            return None

    def _key_begin(self, line):
        """
        获取一个key的键值
        :param line:
        :return:
        """
        if not (
            line.startswith(
                self.key_pre) and line.endswith(
                self.key_post)):
            return False

        line = line.replace(self.key_pre, '').replace(self.key_post, '')
        if line:
            chars = set(line)
            for char in chars:
                if char in self.key_pre or char in self.key_post:
                    return False
            return line
        else:
            return False

    def read_from_path(self, path):
        """
        从文件中读取数据
        :param path:
        :return:
        """
        result = []
        curr_dict = None
        curr_list = None

        with codecs.open(path, encoding='utf8') as fi:
            for line in fi:
                line = line.strip()
                if not line:
                    continue

                sec_begin = self._section_begin(line)
                if sec_begin is not False:
                    curr_dict = {}
                    result.append(curr_dict)
                    if sec_begin is not None:
                        curr_dict['_SN_'] = sec_begin
                    continue

                key_begin = self._key_begin(line)
                if key_begin is not False:
                    curr_list = []
                    curr_dict[key_begin] = curr_list
                    continue

                # 正文
                curr_list.append(line)

        return result


class TextDictWriter(TextDictBase):
    """
    写文件
    """

    def write_to_path(
            self,
            path,
            dicts,
            sn_key='_SN_',
            keys=None,
            keys_b1=None):
        """
        写入到文件
        :param path:
        :param dicts:
        :return:
        """
        with codecs.open(path, 'w', encoding='utf8') as fo:
            for dict_ in dicts:
                print(
                    self.sn_pre,
                    dict_.get(
                        sn_key,
                        ''),
                    self.sn_post,
                    file=fo,
                    sep='')
                for key, value in dict_.items():
                    print(self.key_pre, key, self.key_post, file=fo, sep='')
                    if isinstance(value, (list, tuple)):
                        for i in value:
                            print(i, file=fo)
                    else:
                        print(value, file=fo)

    def set_fo(self, fo):
        self.fo = fo

    def write(self, dict_, cols=None, sn_key='_SN_'):
        if cols is None:
            cols = dict_.keys()

        print(
            self.sn_pre,
            dict_.get(
                sn_key,
                ''),
            self.sn_post,
            file=self.fo,
            sep='')
        for key in cols:
            values = dict_[key]
            print(self.key_pre, key, self.key_post, file=self.fo, sep='')
            if isinstance(values, (list, tuple)):
                for i in values:
                    print(i, file=self.fo)
            else:
                print(values, file=self.fo)

    def get_fo(self):
        return self.fo


class TextDictWriterWithSN(TextDictWriter):

    def write_to_path(
            self,
            path,
            dicts,
            cols=None,
            sn_key='_SN_',
            keys_snn0={},
            sep="||"):
        """
        写入到文件
        :param path:
        :param dicts:
        :return:
        """
        with codecs.open(path, 'w', encoding='utf8') as fo:
            self.fo = fo
            for dict_ in dicts:
                self.write(dict_, cols, sn_key, keys_snn0, sep)

    def write(self, dict_, cols=None, sn_key='_SN_', keys_snn0={}, sep="||"):
        if cols is None:
            cols = dict_.keys()

        print(
            self.sn_pre,
            dict_.get(
                sn_key,
                ''),
            self.sn_post,
            file=self.fo,
            sep='')
        for key in cols:
            print(self.key_pre, key, self.key_post, file=self.fo, sep='')

            values = dict_.get(key, [''])
            begin_sn = keys_snn0.get(key, 0)
            for i, line in enumerate(values, begin_sn):
                base_str = u'{:>3}:{}'
                if isinstance(line, (list, tuple)):
                    str_ = sep.join(line)
                else:
                    str_ = line
                print(base_str.format(i, str_), file=self.fo)


class TextDictReaderWriter(TextDictReader, TextDictWriter):
    pass
